/*
 * Copyright (c) 2017. 恒昌互联网运营中心.
 */
package com.credithc.eagleeye.thread;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
/**
 * 描 述: 分布式SOA服务调用栈信息<br/>
 * 作 者: zhangjin<br/>
 * 创 建：2016年06月01日<br/>
 * 版 本：v1.0.0<br>
 * <p/>
 * 历 史: (版本) 作者 时间 注释 <br/>
 */
public class TraceInfo {
    final ReentrantLock lock = new ReentrantLock();
    /**
     * 跟踪ID
     */
    private String traceId;
    /**
     * rpc调用层级,从1.1开始，每新一级结尾增加.1
     **/
    private String hierarchy;
    /**
     * 当前级别序号
     */
    private AtomicInteger sequenceNo;
    /**
     * 用户相关信息
     */
    private Map<String,String> userInfo;

    public TraceInfo addSequenceNo() {
        try {
            lock.lock();
            this.sequenceNo.incrementAndGet();
        }finally {
            lock.unlock();
        }
        return this;
    }
    public TraceInfo addHierarchy() {
        try {
            lock.lock();
            this.hierarchy = getRpcId();
            this.sequenceNo = new AtomicInteger(0);
        }finally {
            lock.unlock();
        }
        return this;
    }
    public TraceInfo(String traceId, String rpcId) {
        this.traceId = traceId;
        setRpcId(rpcId);
        this.userInfo = new HashMap<>();
    }
    public TraceInfo(String traceId, String rpcId,Map<String,String> userInfo) {
        this.traceId = traceId;
        setRpcId(rpcId);
        this.userInfo = userInfo;
    }
    public TraceInfo() {
        this.traceId = UUID.randomUUID().toString().replace("-", "");
        this.hierarchy = "";
        this.sequenceNo = new AtomicInteger(1);
        this.userInfo = new HashMap<>();
    }
    /**
     * 获取 跟踪ID
     *
     * @return traceId
     */
    public String getTraceId() {
        return traceId;
    }
    /**
     * 设置 跟踪ID
     *
     * @param traceId
     */
    public void setTraceId(String traceId) {
        this.traceId = traceId;
    }
    /**
     * 获取 当前RpcId
     *
     * @return rpcId
     */
    public String getRpcId() {
        if(StringUtils.isBlank(hierarchy)){
            return sequenceNo.get()+"";
        }
        return hierarchy + "." + sequenceNo.get();
    }

    public Map<String, String> getUserInfo() {
        return userInfo;
    }
    public void setUserInfo(Map<String, String> userInfo) {
        this.userInfo = userInfo;
    }

    /**
     * 设置 rpc调用层级,从1.1开始，每级递增0.1*
     *
     * @param rpcId
     */
    public void setRpcId(String rpcId) {
        int lastDotIndex = StringUtils.lastIndexOf(rpcId, ".");
        if(lastDotIndex>-1) {
            this.hierarchy = rpcId.substring(0, lastDotIndex);
            this.sequenceNo = new AtomicInteger(Integer.parseInt(rpcId.substring(lastDotIndex + 1)));
        }else{
            this.hierarchy = "";
            this.sequenceNo = new AtomicInteger(Integer.parseInt(rpcId));
        }
    }
    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("TraceInfo{");
        sb.append("traceId='").append(traceId).append('\'');
        sb.append(", rpcId=").append(getRpcId());
        sb.append('}');
        return sb.toString();
    }
}
